import numpy as np
from sklearn.decomposition import PCA
import pandas as pd


def meanX(dataX):
    # axis=0表示依照列来求均值。假设输入list,则axis=1
    return np.mean(dataX, axis=0)


def pcaByMySelf(x_mat, k):
    # 1 计算均值
    average = meanX(x_mat)
    m, n = np.shape(x_mat)
    # 2 每个数据-均值
    avg_matrix = np.tile(average, (m, 1))
    data_adjust = x_mat - avg_matrix
    # 3 计算协方差矩阵
    cov_x = np.cov(data_adjust.T)  # 计算协方差矩阵

    # 4 求解协方差矩阵的特征值和特征向量
    feat_value, feat_vec = np.linalg.eig(cov_x)  # 求解协方差矩阵的特征值和特征向量

    # 5 依照featValue进行从大到小排序,加负号是降序的
    index = np.argsort(-feat_value)

    if k > n:
        print("k must lower than feature number")
        return
    else:
        # 注意特征向量时列向量。而numpy的二维矩阵(数组)a[m][n]中，a[1]表示第1行值
        select_vec = np.matrix(feat_vec.T[index[:k]])  # 所以这里须要进行转置
        vec_T = select_vec.T
        data_adjust = data_adjust.values  # ndarray
        # final_data = np.mat(data_adjust) * vec_T
        final_data = np.matmul(np.mat(data_adjust), vec_T)
        # final_data = np.mat(data_adjust, vec_T)
        final_data = data_adjust * vec_T

        # recon_data = (final_data *  select_vec) + average
        recon_data = np.matmul(final_data, select_vec)
        # recon_data = np.add(recon_data, average)
    return final_data, recon_data


if __name__ == "__main__":
    # pandas读入
    data = pd.read_csv('data/Advertising.csv')  # TV、Radio、Newspaper、Sales
    x = data[['TV', 'Radio', 'Newspaper']]
    y = data['Sales']

    # PCA算法
    # x = np.array([[1, 1, 1], [0, 0, -1], [1, -1, 1], [-1, 1, 0]]).T
    pca = PCA(n_components=1)
    newArray = pca.fit_transform(x)
    print("PCA降维调用函数结果：\n", newArray)

    pca,d_o = pcaByMySelf(x, 1)
    print("PCA降维手动计算结果：\n", pca,'\n------------------------\n:',d_o)
